﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using RPSImporter.Models;
using System.Reflection;
using RPSImporter.Infrastructure.Attributes;
using RPSImporter.Infrastructure;
using System.Data;
using RPSImporter.Services.Data;
using RPSImporter.Models.Settings;

namespace RPSImporter.Services
{
   public class DatabaseSvc
   {
      #region Singleton
      static DatabaseSvc instance = null;

      DatabaseSvc()
      {
         this.Messages = new List<string>();
      }

      public static DatabaseSvc Instance
      {
         get
         {
            if (instance == null)
            {
               instance = new DatabaseSvc();
            }
            return instance;
         }
      }
      #endregion

      public IList<string> Messages { get; set; }

      private RpsDBDataContext dBContext;
      public RpsDBDataContext DBContext
      {
         get
         {
            if (this.dBContext == null)
            {
               this.dBContext = new RpsDBDataContext();
            }
            return this.dBContext;
         }
      }

      private RPSImporterContext settings;
      public RPSImporterContext Settings
      {
         get
         {
            if (this.settings == null)
            {
               this.settings = new RPSImporterContext();
            }
            return this.settings;
         }
      }

      public void Import<T>(DataTable dt) where T : IModel
      {
         DataColumn[] columns = new DataColumn[dt.Columns.Count];
         dt.Columns.CopyTo(columns, 0);
         string[] columnNames = columns.Select(c => c.Caption).ToArray();
         IList<T> entities = new List<T>();

         foreach (DataRow row in dt.Rows)
         {
            var ctorInfo = typeof(T).GetConstructor(Type.EmptyTypes);
            T entity = (T)ctorInfo.Invoke(null);
            for (int i = 0; i < dt.Columns.Count; i++)
            {
               entity.Data.Add(columnNames[i], row[columnNames[i]].ToString());
            }
            if (!entity.Data.All(e => String.IsNullOrEmpty(e.Value)))
            {
               entities.Add(entity);
            }
         }
         this.Import<T>(entities);
      }

      public void Import(DataTable dt, Type model)
      {
         DataColumn[] columns = new DataColumn[dt.Columns.Count];
         dt.Columns.CopyTo(columns, 0);
         string[] columnNames = columns.Select(c => c.Caption).ToArray();
         IList<IModel> entities = new List<IModel>();

         foreach (DataRow row in dt.Rows)
         {
            var entity = model.GetConstructor(Type.EmptyTypes).Invoke(null);
            for (int i = 0; i < dt.Columns.Count; i++)
            {
               ((IModel)entity).Data.Add(columnNames[i], row[columnNames[i]].ToString());
            }
            if (!((IModel)entity).Data.All(e => String.IsNullOrEmpty(e.Value)))
            {
               entities.Add((IModel)entity);
               if (entities.Count == 200)
               {
                  this.Import<IModel>(entities);
                  entities.Clear();
               }
            }
         }
         this.Import<IModel>(entities);
      }

      private void Import<T>(IList<T> list) where T : IModel
      {
         this.Messages.Clear();
         foreach (var p in list)
         {
            if (p.Import())
            {
               string msg = String.Format("{0}\t imported successfully", p.Data.First().Value);
               this.Messages.Add(msg);
            }
            else
            {
               this.Messages.Add(p.Error);
            }
         }
      }

      public void InitializeSettings()
      {
         #region Users
         if (this.Settings.Users.Count() == 0)
         {
            RPSImporter.Models.User user = new User()
            {
               UserName = "dmd",
               UserPassword = "dmd",
               IsAdmin = true,
            };
            this.Settings.Users.Add(user);
         }
         #endregion

         #region General
         if (this.Settings.GeneralSettings.Count() == 0)
         {
            GeneralSettings settings = new GeneralSettings()
            {
               CompanyFileName = "SiegeSocial",
               EnterpriseFileName = "Etablissement",
               ExternalEnterprisesFileName = "EnteprisesExtérieures",
               HierarchyFileName = "OrganisationFonctionnelle",
               PersonsFileName = "Personnel",
               HoursHierarchyFileName = "HeuresOrganisationFonctionnelle",
               HoursPersonFileName = "HeuresPersonnel",
               CsvDelimiter = "|",
               IsMultiColumnPersonImport = false,
            };
            this.Settings.GeneralSettings.Add(settings);
         }
         #endregion

         #region Company
         if (this.Settings.CompanyFileSettings.Count() == 0)
         {
            CompanyFileSettings settings = new CompanyFileSettings()
            {
               Address1 = "Adresse 1",
               Address2 = "Adresse 2",
               ChCasePostale = "Boite postale",
               City = "Ville",
               Country = "Pays",
               Email = "E-Mail",
               Fax = "Fax",
               Name = "Nom du Siège social",
               Phone = "Téléphone",
               PostalBox = "Boite postale",
               PostalCode = "Code Postal",
               USZipCode = "Code Postal",
               Website = "Website",
            };
            this.Settings.CompanyFileSettings.Add(settings);
         }
         #endregion

         #region Enterprise
         if (this.Settings.EnterpriseFileSettings.Count() == 0)
         {
            EnterpriseFileSettings settings = new EnterpriseFileSettings()
            {
               Name = "Nom de l’Etablissement",
               Address1 = "Adresse 1",
               Address2 = "Adresse 2",
               City = "Ville",
               PostalCode = "Code Postal",
               PostalBox = "Boite postale",
               Phone = "Téléphone",
               Fax = "Fax",
               Email = "E-Mail",
               ContactPerson = "Personne à contacter",
               ActivitySector = "Activité économique",
               NoSiret = "N° SIRET",
               CodeRisque = "Code Risque",
               CodeAPE = "Code APE",
            };
            this.Settings.EnterpriseFileSettings.Add(settings);
         }
         #endregion

         #region Hierarchy
         if (this.Settings.HierarchyFileSettings.Count() == 0)
         {
            HierarchyFileSettings settings = new HierarchyFileSettings()
            {
               Code = "Code unique",
               CodeParent = "Code unique parent",
               Name = "Nom",
            };
            this.Settings.HierarchyFileSettings.Add(settings);
         }
         #endregion

         #region HoursHierarchy
         if (this.Settings.HoursHierarchyFileSettings.Count() == 0)
         {
            HoursHierarchyFileSettings settings = new HoursHierarchyFileSettings()
            {
               Year = "Année",
               Month = "Mois",
               HierarchyCode = "Code unique hiérarchie",
               SubTratamentFBTotal = "Heures sous-traitant totales",
               SubTratamentFBEfectiv = "Effectif sous-traitants total",
               SubTratamentFTotal = "Heures sous-traitant Femme",
               SubTratamentFEfectiv = "Effectif sous-traitants Femme",
               SubTratamentBTotal = "Heures sous-traitant homme",
               SubTratamentBEfectiv = "Effectif sous-traitants homme",

               InternFBTotal = "Heures internes totales",
               InternFBEfectiv = "Effectif interne total",
               InternFTotal = "Heures internes Femme",
               InternFEfectiv = "Effectif interne Femme",
               InternBTotal = "Heures internes homme",
               InternBEfectiv = "Effectif interne homme",

               InterimarFBTotal = "Heures intérimaires totales",
               InterimarFBEfectiv = "Effectif intérimaire total",
               InterimarFTotal = "Heures intérimaires Femme",
               InterimarFEfectiv = "Effectif intérimaire Femme",
               InterimarBTotal = "Heures intérimaires homme",
               InterimarBEfectiv = "Effectif intérimaire homme",

               GlobalFBTotal = "Heures globales totales",
               GlobalFBEfectiv = "Effectif global",
               GlobalFTotal = "Heures globales Femme",
               GlobalFEfectiv = "Effectif global Femme",
               GlobalBTotal = "Heures globales homme",
               GlobalBEfectiv = "Effectif global homme",

               ExternFBTotal = "Heures Externes totales",
               ExternFBEfectiv = "Effectif externe total",
               ExternFTotal = "Heures Externes Femme",
               ExternFEfectiv = "Effectif externe Femme",
               ExternBTotal = "Heures Externes homme",
               ExternBEfectiv = "Effectif externe homme",

               OtherFBTotal = "Heures autres totales",
               OtherFBEfectiv = "Effectif autre total",
               OtherFTotal = "Heures autres Femme",
               OtherFEfectiv = "Effectif autre Femme",
               OtherBTotal = "Heures autres homme",
               OtherBEfectiv = "Effectif autre homme",
            };
            this.Settings.HoursHierarchyFileSettings.Add(settings);
         }
         #endregion

         #region HoursPerson
         if (this.Settings.HoursPersonFileSettings.Count() == 0)
         {
            HoursPersonFileSettings settings = new HoursPersonFileSettings()
            {
               Year = "Année",
               Month = "Mois",
               NrHours = "Nombre d’heures",
               NrSecuriteSociale = "N° Sécurité sociale (NIR)",
               KeyNIR = "Clé (NIR)",
            };
            this.Settings.HoursPersonFileSettings.Add(settings);
         }
         #endregion

         #region Person
         if (this.Settings.PersonFileSettings.Count() == 0)
         {
            PersonFileSettings settings = new PersonFileSettings()
            {
               FirstName = "Nom",
               LastName = "Prénom",
               Gender = "Sexe",
               MaidenName = "Nom de jeune fille",
               BadgeNumber = "Numéro de matricule",
               Age = "Age",
               BirthDate = "Date de naissance",
               CivilState = "Etat civil",
               Language = "Langue",
               Nationality = "Nationalité",
               CategorieSante = "Personnel catégorie santé",
               SocialSecurityNumber = "N° de sécurité sociale (NIR)",
               ControlKey = "Clé (NIR)",
               Company = "Siège social",
               Enterprise = "Etablissement",
               Hierarchy = "Rattachement hiérarchique",
               Country = "Pays",
               TypePersonel = "Type personnel",
               WorkingHoursName = "Nom Horaire",
               WorkingHoursCode = "Code Horaire",
               Occupation = "Fonction",
               StartingDate = "Depuis le (fonction)",
               Proffesion = "Profession",
               Qualification = "Qualification",
               HirementDate = "Date d’engagement (embauche)",
               Address1 = "Adresse 1",
               City = "Ville",
               ZipCode = "Code postal",
               Phone = "Tél# Fixe",
               SocialWorker = "Secouriste",
            };
            this.Settings.PersonFileSettings.Add(settings);
         }
         #endregion

         this.Settings.SaveChanges();
      }

      public void ReinitSettings()
      {
          this.settings = new RPSImporterContext();
      }
   }
}